home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / tcsh / dist / ed.inputl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-21  |  17.0 KB  |  704 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.01/RCS/ed.inputl.c,v 3.15 1991/12/19 22:34:14 christos Exp $ */
  2. /*
  3.  * ed.inputl.c: Input line handling.
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "sh.h"
  38.  
  39. RCSID("$Id: ed.inputl.c,v 3.15 1991/12/19 22:34:14 christos Exp $")
  40.  
  41. #include "ed.h"
  42. #include "ed.defns.h"        /* for the function names */
  43. #include "tw.h"            /* for twenex stuff */
  44.  
  45. #define OKCMD (INBUFSIZE+INBUFSIZE)
  46. extern CCRETVAL e_up_hist();
  47. extern CCRETVAL e_expand_history();
  48.  
  49. /* ed.inputl -- routines to get a single line from the input. */
  50.  
  51. extern bool tellwhat;
  52. extern bool MapsAreInited;
  53. extern bool Tty_raw_mode;
  54.  
  55. /* mismatched first character */
  56. static Char mismatch[] = {'!', '\\', '^', '-', '%', '\0'};
  57.  
  58. static    int    GetNextCommand    __P((KEYCMD *, Char *));
  59. static    int    SpellLine    __P((int));
  60. static    void    RunCommand    __P((Char *));
  61. static void     doeval1        __P((Char **));
  62.  
  63. /* CCRETVAL */
  64. int
  65. Inputl()
  66. {
  67.     CCRETVAL retval;
  68.     KEYCMD  cmdnum = 0;
  69.     extern KEYCMD NumFuns;
  70.     unsigned char tch;        /* the place where read() goes */
  71.     Char    ch;
  72.     int     num;        /* how many chars we have read at NL */
  73.     int        expnum;
  74.     struct varent *crct = adrof(STRcorrect);
  75.     struct varent *autol = adrof(STRautolist);
  76.     struct varent *matchbeep = adrof(STRmatchbeep);
  77.     struct varent *imode = adrof(STRinputmode);
  78.     Char   *SaveChar, *CorrChar;
  79.     Char    Origin[INBUFSIZE], Change[INBUFSIZE];
  80.     int     matchval;        /* from tenematch() */
  81.  
  82.     if (!MapsAreInited)        /* double extra just in case */
  83.     ed_InitMaps();
  84.  
  85.     ClearDisp();        /* reset the display stuff */
  86.     ResetInLine();        /* reset the input pointers */
  87.     if (GettingInput)
  88.     MacroLvl = -1;        /* editor was interrupted during input */
  89.  
  90. #ifdef FIONREAD
  91.     if (!Tty_raw_mode && MacroLvl < 0) {
  92.     long    chrs = 0;
  93.  
  94.     (void) ioctl(SHIN, FIONREAD, (ioctl_t) & chrs);
  95.     if (chrs == 0) {
  96.         if (Rawmode() < 0)
  97.         return 0;
  98.     }
  99.     }
  100. #endif
  101.  
  102.     GettingInput = 1;
  103.     NeedsRedraw = 0;
  104.  
  105.     if (tellwhat) {
  106.     copyn(InputBuf, WhichBuf, INBUFSIZE);
  107.     LastChar = InputBuf + (LastWhich - WhichBuf);
  108.     Cursor = InputBuf + (CursWhich - WhichBuf);
  109.     tellwhat = 0;
  110.     Hist_num = HistWhich;
  111.     }
  112.     if (Expand) {
  113.     (void) e_up_hist(0);
  114.     Expand = 0;
  115.     }
  116.     Refresh();            /* print the prompt */
  117.  
  118.     for (num = OKCMD; num == OKCMD;) {    /* while still editing this line */
  119. #ifdef DEBUG_EDIT
  120.     if (Cursor > LastChar)
  121.         xprintf("Cursor > LastChar\r\n");
  122.     if (Cursor < InputBuf)
  123.         xprintf("Cursor < InputBuf\r\n");
  124.     if (Cursor > InputLim)
  125.         xprintf("Cursor > InputLim\r\n");
  126.     if (LastChar > InputLim)
  127.         xprintf("LastChar > InputLim\r\n");
  128.     if (InputLim != &InputBuf[INBUFSIZE - 2])
  129.         xprintf("InputLim != &InputBuf[INBUFSIZE-2]\r\n");
  130.     if ((!DoingArg) && (Argument != 1))
  131.         xprintf("(!DoingArg) && (Argument != 1)\r\n");
  132.     if (CcKeyMap[0] == 0)
  133.         xprintf("CcKeyMap[0] == 0 (maybe not inited)\r\n");
  134. #endif
  135.  
  136.     /* if EOF or error */
  137.     if ((num = GetNextCommand(&cmdnum, &ch)) != OKCMD) {
  138.         break;
  139.     }
  140.  
  141.     if (cmdnum >= NumFuns) {/* BUG CHECK command */
  142. #ifdef DEBUG_EDIT
  143.         xprintf("ERROR: illegal command from key 0%o\r\n", ch);
  144. #endif
  145.         continue;        /* try again */
  146.     }
  147.  
  148.     /* now do the real command */
  149.     retval = (*CcFuncTbl[cmdnum]) (ch);
  150.  
  151.     /* save the last command here */
  152.     LastCmd = cmdnum;
  153.  
  154.     /* use any return value */
  155.     switch (retval) {
  156.  
  157.     case CC_REFRESH:
  158.         Refresh();
  159.         /* fall through */
  160.     case CC_NORM:        /* normal char */
  161.         Argument = 1;
  162.         DoingArg = 0;
  163.         /* fall through */
  164.     case CC_ARGHACK:    /* Suggested by Rich Salz */
  165.         /* <rsalz@pineapple.bbn.com> */
  166.         break;        /* keep going... */
  167.  
  168.     case CC_EOF:        /* end of file typed */
  169. #ifdef notdef
  170.         PromptBuf[0] = '\0';
  171. #endif
  172.         num = 0;
  173.         break;
  174.  
  175.     case CC_WHICH:        /* tell what this command does */
  176.         tellwhat = 1;
  177.         copyn(WhichBuf, InputBuf, INBUFSIZE);
  178.         LastWhich = WhichBuf + (LastChar - InputBuf);
  179.         CursWhich = WhichBuf + (Cursor - InputBuf);
  180.         *LastChar++ = '\n';    /* for the benifit of CSH */
  181.         HistWhich = Hist_num;
  182.         Hist_num = 0;    /* for the history commands */
  183.         num = LastChar - InputBuf;    /* number characters read */
  184. #ifdef notdef
  185.         ResetInLine();    /* reset the input pointers */
  186. #endif
  187.         break;
  188.  
  189.     case CC_NEWLINE:    /* normal end of line */
  190.         if (crct && (!Strcmp(*(crct->vec), STRcmd) ||
  191.              !Strcmp(*(crct->vec), STRall))) {
  192.         copyn(Origin, InputBuf, INBUFSIZE);
  193.         SaveChar = LastChar;
  194.         if (SpellLine(!Strcmp(*(crct->vec), STRcmd)) == 1) {
  195.             copyn(Change, InputBuf, INBUFSIZE);
  196.             *Strchr(Change, '\n') = '\0';
  197.             CorrChar = LastChar;    /* Save the corrected end */
  198.             LastChar = InputBuf;    /* Null the current line */
  199.             Beep();
  200.             printprompt(2, Change);
  201.             Refresh();
  202.             (void) read(SHIN, (char *) &tch, 1);
  203.             ch = tch;
  204.             if (ch == 'y' || ch == ' ') {
  205.             LastChar = CorrChar;    /* Restore the corrected end */
  206.             xprintf("yes\n");
  207.             }
  208.             else {
  209.             (void) copyn(InputBuf, Origin, INBUFSIZE);
  210.             LastChar = SaveChar;
  211.             if (ch == 'e') {
  212.                 xprintf("edit\n");
  213.                 *LastChar-- = '\0';
  214.                 Cursor = LastChar;
  215.                 printprompt(3, NULL);
  216.                 Refresh();
  217.                 break;
  218.             }
  219.             xprintf("no\n");
  220.             }
  221.             flush();
  222.         }
  223.         }            /* end CORRECT code */
  224.         tellwhat = 0;    /* just in case */
  225.         Hist_num = 0;    /* for the history commands */
  226.         num = LastChar - InputBuf;    /* return the number of chars read */
  227.         /*
  228.          * For continuation lines, we set the prompt to prompt 2
  229.          */
  230.         if (imode) {
  231.         if (!Strcmp(*(imode->vec), STRinsert))
  232.             inputmode = MODE_INSERT;
  233.         else if (!Strcmp(*(imode->vec), STRoverwrite))
  234.             inputmode = MODE_REPLACE;
  235.         }
  236.         printprompt(1, NULL);
  237. #ifdef notdef
  238.         ResetInLine();    /* reset the input pointers */
  239.         PromptBuf[0] = '\0';
  240. #endif
  241.         break;
  242.  
  243.     case CC_CORRECT:
  244.         if (tenematch(InputBuf, INBUFSIZE, Cursor - InputBuf,
  245.               SPELL) < 0)
  246.         Beep();        /* Beep = No match/ambiguous */
  247.         if (NeedsRedraw) {
  248.         ClearLines();
  249.         ClearDisp();
  250.         NeedsRedraw = 0;
  251.         }
  252.         Refresh();
  253.         Argument = 1;
  254.         DoingArg = 0;
  255.         break;
  256.  
  257.     case CC_CORRECT_L:
  258.         if (SpellLine(FALSE) < 0)
  259.         Beep();        /* Beep = No match/ambiguous */
  260.         if (NeedsRedraw) {
  261.         ClearLines();
  262.         ClearDisp();
  263.         NeedsRedraw = 0;
  264.         }
  265.         Refresh();
  266.         Argument = 1;
  267.         DoingArg = 0;
  268.         break;
  269.  
  270.  
  271.     case CC_COMPLETE:
  272.         if (adrof(STRautoexpand))
  273.         (void) e_expand_history(0);
  274.         /*
  275.          * Modified by Martin Boyer (gamin@ireq-robot.hydro.qc.ca):
  276.          * A separate variable now controls beeping after
  277.          * completion, independently of autolisting.
  278.          */
  279.         expnum = Cursor - InputBuf;
  280.         switch (matchval = 
  281.             tenematch(InputBuf, INBUFSIZE, Cursor-InputBuf, RECOGNIZE)) {
  282.         case 1:
  283.         if (non_unique_match && matchbeep &&
  284.             (Strcmp(*(matchbeep->vec), STRnotunique) == 0))
  285.             Beep();
  286.         break;
  287.         case 0:
  288.         if (matchbeep) {
  289.             if (Strcmp(*(matchbeep->vec), STRnomatch) == 0 ||
  290.             Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
  291.             Strcmp(*(matchbeep->vec), STRnotunique) == 0)
  292.             Beep();
  293.         }
  294.         else
  295.             Beep();
  296.         break;
  297.         default:
  298.         if (matchval < 0) {    /* Error from tenematch */
  299.             Beep();
  300.             break;
  301.         }
  302.         if (matchbeep) {
  303.             if ((Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
  304.              Strcmp(*(matchbeep->vec), STRnotunique) == 0))
  305.             Beep();
  306.         }
  307.         else
  308.             Beep();
  309.         /*
  310.          * Addition by David C Lawrence <tale@pawl.rpi.edu>: If an 
  311.          * attempted completion is ambiguous, list the choices.  
  312.          * (PWP: this is the best feature addition to tcsh I have 
  313.          * seen in many months.)
  314.          */
  315.         if (autol && (Strcmp(*(autol->vec), STRambiguous) != 0 || 
  316.                      expnum == Cursor - InputBuf)) {
  317.             PastBottom();
  318.             (void) tenematch(InputBuf, INBUFSIZE, Cursor-InputBuf, LIST);
  319.         }
  320.         break;
  321.         }
  322.         if (NeedsRedraw) {
  323.         PastBottom();
  324.         ClearLines();
  325.         ClearDisp();
  326.         NeedsRedraw = 0;
  327.         }
  328.         Refresh();
  329.         Argument = 1;
  330.         DoingArg = 0;
  331.         break;
  332.  
  333.     case CC_LIST_CHOICES:
  334.         /* should catch ^C here... */
  335.         if (tenematch(InputBuf, INBUFSIZE, Cursor - InputBuf, LIST) < 0)
  336.         Beep();
  337.         Refresh();
  338.         Argument = 1;
  339.         DoingArg = 0;
  340.         break;
  341.  
  342.     case CC_LIST_GLOB:
  343.         if (tenematch(InputBuf, INBUFSIZE, Cursor - InputBuf, GLOB) < 0)
  344.         Beep();
  345.         Refresh();
  346.         Argument = 1;
  347.         DoingArg = 0;
  348.         break;
  349.  
  350.     case CC_EXPAND_GLOB:
  351.         if (tenematch(InputBuf, INBUFSIZE, Cursor - InputBuf,
  352.               GLOB_EXPAND) <= 0)
  353.         Beep();        /* Beep = No match */
  354.         if (NeedsRedraw) {
  355.         ClearLines();
  356.         ClearDisp();
  357.         NeedsRedraw = 0;
  358.         }
  359.         Refresh();
  360.         Argument = 1;
  361.         DoingArg = 0;
  362.         break;
  363.  
  364.     case CC_NORMALIZE_PATH:
  365.         if (tenematch(InputBuf, INBUFSIZE, Cursor - InputBuf,
  366.               PATH_NORMALIZE) <= 0)
  367.         Beep();        /* Beep = No match */
  368.         if (NeedsRedraw) {
  369.         ClearLines();
  370.         ClearDisp();
  371.         NeedsRedraw = 0;
  372.         }
  373.         Refresh();
  374.         Argument = 1;
  375.         DoingArg = 0;
  376.         break;
  377.  
  378.     case CC_EXPAND_VARS:
  379.         if (tenematch(InputBuf, INBUFSIZE, Cursor - InputBuf,
  380.               VARS_EXPAND) <= 0)
  381.         Beep();        /* Beep = No match */
  382.         if (NeedsRedraw) {
  383.         ClearLines();
  384.         ClearDisp();
  385.         NeedsRedraw = 0;
  386.         }
  387.         Refresh();
  388.         Argument = 1;
  389.         DoingArg = 0;
  390.         break;
  391.  
  392.     case CC_HELPME:
  393.         xputchar('\n');
  394.         /* should catch ^C here... */
  395.         (void) tenematch(InputBuf, INBUFSIZE, LastChar - InputBuf,
  396.                  PRINT_HELP);
  397.         Refresh();
  398.         Argument = 1;
  399.         DoingArg = 0;
  400.         break;
  401.  
  402.     case CC_FATAL:        /* fatal error, reset to known state */
  403. #ifdef DEBUG_EDIT
  404.         xprintf("*** editor fatal ERROR ***\r\n\n");
  405. #endif                /* DEBUG_EDIT */
  406.         /* put (real) cursor in a known place */
  407.         ClearDisp();    /* reset the display stuff */
  408.         ResetInLine();    /* reset the input pointers */
  409.         Refresh();        /* print the prompt again */
  410.         Argument = 1;
  411.         DoingArg = 0;
  412.         break;
  413.  
  414.     case CC_ERROR:
  415.     default:        /* functions we don't know about */
  416.         DoingArg = 0;
  417.         Argument = 1;
  418.         Beep();
  419.         flush();
  420.         break;
  421.     }
  422.     }
  423.     (void) Cookedmode();    /* make sure the tty is set up correctly */
  424.     GettingInput = 0;
  425.     flush();            /* flush any buffered output */
  426.     return num;
  427. }
  428.  
  429. void
  430. PushMacro(str)
  431.     Char   *str;
  432. {
  433.     if (str != NULL && MacroLvl + 1 < MAXMACROLEVELS) {
  434.     MacroLvl++;
  435.     KeyMacro[MacroLvl] = str;
  436.     }
  437.     else {
  438.     Beep();
  439.     flush();
  440.     }
  441. }
  442.  
  443. /*
  444.  * Like eval, only using the current file descriptors
  445.  */
  446. static Char **gv = NULL;
  447.  
  448. static void
  449. doeval1(v)
  450.     Char **v;
  451. {
  452.     Char  **oevalvec;
  453.     Char   *oevalp;
  454.     int     my_reenter;
  455.     Char  **savegv;
  456.     jmp_buf osetexit;
  457.  
  458.     oevalvec = evalvec;
  459.     oevalp = evalp;
  460.     savegv = gv;
  461.  
  462.  
  463.     gflag = 0, tglob(v);
  464.     if (gflag) {
  465.     gv = v = globall(v);
  466.     gargv = 0;
  467.     if (v == 0)
  468.         stderror(ERR_NOMATCH);
  469.     v = copyblk(v);
  470.     }
  471.     else {
  472.     gv = NULL;
  473.     v = copyblk(v);
  474.     trim(v);
  475.     }
  476.  
  477.     getexit(osetexit);
  478.  
  479.     /* PWP: setjmp/longjmp bugfix for optimizing compilers */
  480. #ifdef cray
  481.     my_reenter = 1;             /* assume non-zero return val */
  482.     if (setexit() == 0) {
  483.         my_reenter = 0;         /* Oh well, we were wrong */
  484. #else /* !cray */
  485.     if ((my_reenter = setexit()) == 0) {
  486. #endif /* cray */
  487.     evalvec = v;
  488.     evalp = 0;
  489.     process(0);
  490.     }
  491.  
  492.     evalvec = oevalvec;
  493.     evalp = oevalp;
  494.     doneinp = 0;
  495.  
  496.     if (gv)
  497.     blkfree(gv);
  498.  
  499.     gv = savegv;
  500.     resexit(osetexit);
  501.     if (my_reenter)
  502.     stderror(ERR_SILENT);
  503. }
  504.  
  505. static void
  506. RunCommand(str)
  507.     Char *str;
  508. {
  509.     Char *cmd[2];
  510.  
  511.     xprintf("\n");    /* Start on a clean line */
  512.  
  513.     cmd[0] = str;
  514.     cmd[1] = NULL;
  515.  
  516.     doeval1(cmd);
  517.     
  518.     ClearLines();
  519.     ClearDisp();
  520.     NeedsRedraw = 1;
  521.     Refresh();
  522. }
  523.  
  524. static int
  525. GetNextCommand(cmdnum, ch)
  526.     KEYCMD *cmdnum;
  527.     register Char *ch;
  528. {
  529.     KEYCMD  cmd = 0;
  530.     int     num;
  531.  
  532.     while (cmd == 0 || cmd == F_XKEY) {
  533.     if ((num = GetNextChar(ch)) != 1) {    /* if EOF or error */
  534.         return num;
  535.     }
  536. #ifdef    KANJI
  537.     if (*ch & META) {
  538.         MetaNext = 0;
  539.         cmd = CcViMap[' '];
  540.         break;
  541.     }
  542.     else
  543. #endif /* KANJI */
  544.     if (MetaNext) {
  545.         MetaNext = 0;
  546.         *ch |= META;
  547.     }
  548.     cmd = CurrentKeyMap[(unsigned char) *ch];
  549.     if (cmd == F_XKEY) {
  550.         XmapVal val;
  551.         switch (GetXkey(ch, &val)) {
  552.         case XK_CMD:
  553.         cmd = val.cmd;
  554.         break;
  555.         case XK_STR:
  556.         PushMacro(val.str);
  557.         break;
  558.         case XK_EXE:
  559.         RunCommand(val.str);
  560.         break;
  561.         default:
  562.         abort();
  563.         break;
  564.         }
  565.     }
  566.     if (!AltKeyMap) 
  567.         CurrentKeyMap = CcKeyMap;
  568.     }
  569.     *cmdnum = cmd;
  570.     return OKCMD;
  571. }
  572.  
  573. int
  574. GetNextChar(cp)
  575.     register Char *cp;
  576. {
  577.     register int num_read;
  578. #if defined(EWOULDBLOCK) || (defined(POSIX) && defined(EAGAIN))
  579. # if defined(FIONBIO) || (defined(F_SETFL) && defined(O_NDELAY))
  580. #  define TRY_AGAIN
  581.     int     tried = 0;
  582. # endif /* FIONBIO || (F_SETFL && O_NDELAY) */
  583. #endif /* EWOULDBLOCK || (POSIX && EAGAIN) */
  584.     unsigned char tcp;
  585.  
  586.     for (;;) {
  587.     if (MacroLvl < 0) {
  588.         if (!Load_input_line())
  589.         break;
  590.     }
  591.     if (*KeyMacro[MacroLvl] == 0) {
  592.         MacroLvl--;
  593.         continue;
  594.     }
  595.     *cp = *KeyMacro[MacroLvl]++ & CHAR;
  596.     if (*KeyMacro[MacroLvl] == 0) {    /* Needed for QuoteMode On */
  597.         MacroLvl--;
  598.     }
  599.     return (1);
  600.     }
  601.  
  602.     if (Rawmode() < 0)        /* make sure the tty is set up correctly */
  603.     return 0;        /* oops: SHIN was closed */
  604.  
  605.     while ((num_read = read(SHIN, (char *) &tcp, 1)) == -1)
  606.     switch (errno) {
  607.         /*
  608.          * Someone might have set our file descriptor to non blocking From
  609.          * Gray Watson (gray%antr.uucp@med.pitt.edu), Thanks!!!
  610.          */
  611. #ifdef EWOULDBLOCK
  612.     case EWOULDBLOCK:
  613. #endif /* EWOULDBLOCK */
  614. #if defined(POSIX) && defined(EAGAIN)
  615. # if defined(EWOULDBLOCK) && EAGAIN != EWOULDBLOCK
  616.     case EAGAIN:
  617. # endif /* EWOULDBLOCK && EAGAIN != EWOULDBLOCK */
  618. #endif /* POSIX && EAGAIN */
  619. #ifdef TRY_AGAIN
  620.         if (!tried) {
  621. # if defined(F_SETFL) && defined(O_NDELAY)
  622.         (void) fcntl(SHIN, F_SETFL,
  623.                  fcntl(SHIN, F_GETFL, 0) & ~O_NDELAY);
  624. # endif /* F_SETFL && O_NDELAY */
  625. # ifdef FIONBIO
  626.         (void) ioctl(SHIN, FIONBIO, (ioctl_t) & tried);
  627. # endif /* FIONBIO */
  628.         tried = 1;
  629.         break;
  630.         }
  631.         *cp = tcp;
  632.         return (num_read);
  633. #endif /* TRY_AGAIN */
  634.     case EINTR:
  635.         break;
  636.     default:
  637. #ifdef DEBUG_EDIT
  638.         xprintf("GetNextChar(): errno == %d\n", errno);
  639. #endif /* DEBUG_EDIT */
  640.         *cp = tcp;
  641.         return num_read;
  642.     }
  643.     *cp = tcp;
  644.     return num_read;
  645. }
  646.  
  647. /*
  648.  * SpellLine - do spelling correction on the entire command line
  649.  * (which may have trailing newline).
  650.  * If cmdonly is set, only check spelling of command words.
  651.  * Return value:
  652.  * -1: Something was incorrectible, and nothing was corrected
  653.  *  0: Everything was correct
  654.  *  1: Something was corrected
  655.  */
  656. static int
  657. SpellLine(cmdonly)
  658.     int     cmdonly;
  659. {
  660.     int     endflag, matchval;
  661.     Char   *argptr, *OldCursor, *OldLastChar;
  662.  
  663.     OldLastChar = LastChar;
  664.     OldCursor = Cursor;
  665.     argptr = InputBuf;
  666.     endflag = 1;
  667.     matchval = 0;
  668.     do {
  669.     while (ismetahash(*argptr) || iscmdmeta(*argptr))
  670.         argptr++;
  671.     for (Cursor = argptr;
  672.          *Cursor != '\0' && !ismetahash(*Cursor) && !iscmdmeta(*Cursor);
  673.          Cursor++);
  674.     if (*Cursor == '\0') {
  675.         Cursor = LastChar;
  676.         if (LastChar[-1] == '\n')
  677.         Cursor--;
  678.         endflag = 0;
  679.     }
  680.     if (!Strchr(mismatch, *argptr) &&
  681.         (!cmdonly || starting_a_command(argptr, InputBuf))) {
  682.         switch (tenematch(InputBuf, INBUFSIZE, Cursor - InputBuf, SPELL)) {
  683.         case 1:        /* corrected */
  684.         matchval = 1;
  685.         break;
  686.         case -1:        /* couldn't be corrected */
  687.         if (!matchval)
  688.             matchval = -1;
  689.         break;
  690.         default:        /* was correct */
  691.         break;
  692.         }
  693.         if (LastChar != OldLastChar) {
  694.         if (argptr < OldCursor)
  695.             OldCursor += (LastChar - OldLastChar);
  696.         OldLastChar = LastChar;
  697.         }
  698.     }
  699.     argptr = Cursor;
  700.     } while (endflag);
  701.     Cursor = OldCursor;
  702.     return matchval;
  703. }
  704.